package xworker.gluon.glisten.control;

import com.gluonhq.charm.glisten.control.CharmListCell;
import com.gluonhq.charm.glisten.control.CharmListView;
import javafx.scene.Node;
import javafx.util.Callback;
import javafx.util.StringConverter;
import org.xmeta.ActionContext;
import org.xmeta.Thing;
import xworker.javafx.beans.property.PropertyFactory;
import xworker.javafx.control.ControlActions;
import xworker.javafx.util.JavaFXUtils;

import java.util.Collection;
import java.util.Comparator;
import java.util.function.Function;

public class CharmListViewActions {
    static{
        PropertyFactory.regist(CharmListView.class, "onPullToRefreshProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.onPullToRefreshProperty();
        });
        PropertyFactory.regist(CharmListView.class, "itemsProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.itemsProperty();
        });
        PropertyFactory.regist(CharmListView.class, "headersFunctionProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.headersFunctionProperty();
        });
        PropertyFactory.regist(CharmListView.class, "headersComparatorProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.headersComparatorProperty();
        });
        PropertyFactory.regist(CharmListView.class, "cellHeaderFactoryProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.cellHeaderFactoryProperty();
        });
        PropertyFactory.regist(CharmListView.class, "floatingHeaderVisibleProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.floatingHeaderVisibleProperty();
        });
        PropertyFactory.regist(CharmListView.class, "refreshIndicatorVisibleProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.refreshIndicatorVisibleProperty();
        });
        PropertyFactory.regist(CharmListView.class, "comparatorProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.comparatorProperty();
        });
        PropertyFactory.regist(CharmListView.class, "placeholderProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.placeholderProperty();
        });
        PropertyFactory.regist(CharmListView.class, "cellFactoryProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.cellFactoryProperty();
        });
        PropertyFactory.regist(CharmListView.class, "converterProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.converterProperty();
        });
        PropertyFactory.regist(CharmListView.class, "selectedItemProperty", o -> {
            CharmListView<?,?> obj = (CharmListView<?,?>) o;
            return obj.selectedItemProperty();
        });
    }

    public static void init(CharmListView<Object, Comparable<Object>> node, Thing thing, ActionContext actionContext){
        ControlActions.init(node, thing, actionContext);

        Callback<CharmListView<Object, Comparable<Object>>, CharmListCell<Object>> cellFactory = JavaFXUtils.getObject(thing, "cellFactory", actionContext);
        if(cellFactory != null){
            node.setCellFactory(cellFactory);
        }

        Callback<CharmListView<Object, Comparable<Object>>, CharmListCell<Object>> cellHeaderFactory = JavaFXUtils.getObject(thing, "cellFactory", actionContext);
        if(cellHeaderFactory != null){
            node.setHeaderCellFactory(cellHeaderFactory);
        }

        Comparator<Object> comparator = JavaFXUtils.getObject(thing, "comparator", actionContext);
        if(comparator != null){
            node.setComparator(comparator);
        }

        StringConverter<Comparable<Object>> converter = JavaFXUtils.getObject(thing, "converter", actionContext);
        if(converter != null){
            node.setConverter(converter);
        }

        if(thing.valueExists("floatingHeaderVisible")){
            node.setFloatingHeaderVisible(thing.getBoolean("floatingHeaderVisible"));
        }

        Comparator<Comparable<Object>> headersComparator= JavaFXUtils.getObject(thing, "headersComparator", actionContext);
        if(headersComparator != null){
            node.setHeaderComparator(headersComparator);
        }

        Function<Object, Comparable<Object>> headersFunction = JavaFXUtils.getObject(thing, "headersFunction", actionContext);
        if(headersFunction != null){
            node.setHeadersFunction(headersFunction);
        }

        Collection<Object> items = JavaFXUtils.getObject(thing, "items", actionContext);
        if(items != null){
            node.itemsProperty().addAll(items);
        }

        Node placeholder = JavaFXUtils.getObject(thing, "placeholder", actionContext);
        if(placeholder != null){
            node.setPlaceholder(placeholder);
        }

        if(thing.valueExists("refreshIndicatorVisible")){
            node.setRefreshIndicatorVisible(thing.getBoolean("refreshIndicatorVisible"));
        }

        Object selectedItem = JavaFXUtils.getObject(thing, "selectedItem", actionContext);
        if(selectedItem != null){
            node.setSelectedItem(selectedItem);
        }
    }

    public static CharmListView<Object, Comparable<Object>> create(ActionContext actionContext){
        Thing self = actionContext.getObject("self");
        CharmListView<Object, Comparable<Object>> node = new CharmListView<>();
        init(node, self, actionContext);

        actionContext.peek().put("parent", node);
        for(Thing child : self.getChilds()){
            child.doAction("create", actionContext);
        }

        actionContext.g().put(self.getMetadata().getName(), node);
        return node;
    }

    @SuppressWarnings("unchecked")
    public static void createCellFactory(ActionContext actionContext){
        Thing self = actionContext.getObject("self");
        CharmListView<Object, Comparable<Object>> parent = actionContext.getObject("parent");
        parent.setCellFactory(charmListView ->{
            ActionContext ac = new ActionContext();
            ac.put("charmListView", charmListView);
            ac.put("parentContext", actionContext);

            for(Thing child : self.getChilds()){
                Object obj = child.doAction("create", ac);
                if(obj instanceof CharmListCell){
                    return (CharmListCell<Object>) obj;
                }
            }

            return null;
        });
    }

    @SuppressWarnings("unchecked")
    public static void createCellHeaderFactory(ActionContext actionContext){
        Thing self = actionContext.getObject("self");
        CharmListView<Object, Comparable<Object>> parent = actionContext.getObject("parent");
        parent.setHeaderCellFactory(charmListView ->{
            ActionContext ac = new ActionContext();
            ac.put("charmListView", charmListView);
            ac.put("parentContext", actionContext);

            for(Thing child : self.getChilds()){
                Object obj = child.doAction("create", ac);
                if(obj instanceof CharmListCell){
                    return (CharmListCell<Object>) obj;
                }
            }

            return null;
        });
    }
}
